Reference-Aware Algorithms - #2153
Conversation
Several headers in exec depend on __storage.hpp.
Allows for template arguments deduced from a completion, for example in: template<typename... Args> void set_value(Args&&...); To be used to determine which completion signature such a completion corresponds to. See P4288.
Provides a turnkey, reference-aware way to store completion signatures for later examination or transmission. See P4288. Note that this implementation diverges from the implementation described in P4288. In order to remain device compatible this implementation stores a __tuple rather than a std::tuple. Therefore storage_for_completion_signature::arguments cannot be provided (since it returns a reference to the directly stored std::tuple, which doesn't exist in this implementation). Moreover to support algorithms which aim to be usable on host and device the implementation in this commit provides both storage_for_completion_signature::forward_arguments and ::__forward_arguments where the latter returns a __tuple and can therefore be marked as being device compatible.
See P4288.
See P4288.
In addition to adding reference awareness also fixes (and brings under test) a previous defect: If decay-copying the result datums threw the successor operation was previously skipped.
See P4288. Also brings the implementation into alignment with the standard: The standard specifies that if storage the value result datums throws the schedule operation is started whereas the previous implementation delivered such a failure inline.
See P4288.
No longer used in favor of storage_for_completion_signatures (which is reference aware).
990160d to
0e15401
Compare
ericniebler
left a comment
There was a problem hiding this comment.
partial review, more coming...
Also contains the following fixes:
continues_onnow implements the standard behavior of scheduling when storing the result datums of the predecessor throwsfinallynow runs the successor even if storing the result datums throws
would be great if these fixes were in a separate PR so i could merge them early.
| using completions_t = | ||
| decltype(sender_t::template get_completion_signatures<sender_t, ex::env<>>()); | ||
|
|
||
| static_assert(ex::__merror<completions_t>); |
There was a problem hiding this comment.
once i fix the constexpr exception support in get_completion_signatures, this test will fail. i think you could change this to static_assert(!ex::sender_in<sender_t, ex::env<>>).
| # define STDEXEC_TUPLE_GET(_Idx) \ | ||
| , static_cast< \ | ||
| __copy_cvref_t<_Tuple&&, decltype(static_cast<_Tuple&&>(__tupl).__val##_Idx)>>( \ | ||
| static_cast<_Tuple&&>(__tupl).__val##_Idx) |
There was a problem hiding this comment.
why is this change necessary? shouldn't static_cast<_Tuple&&>(__tupl).__val##_Idx already have the correct value category if __val##_Idx has reference type?
There was a problem hiding this comment.
Given:
struct foo { int&& bar; };Both decltype((std::declval<foo>().bar)) and decltype((std::declval<foo&>().bar)) are int&.
| __concat_completion_signatures_t<typename __storage_t::completion_signatures, | ||
| completion_signatures<set_error_t(std::exception_ptr)>>; | ||
|
|
||
| static consteval auto get_completion_signatures() |
There was a problem hiding this comment.
should the return type of this function always be the same as the type type alias?
| && __completes_inline_for<set_stopped_t, _Sender, _Env...>; | ||
|
|
||
| template <class _Value, bool _Inline> | ||
| template <class _Sender, class _Promise, class _Value, bool _Inline> |
There was a problem hiding this comment.
i try to keep sender types out of the types of receivers (and awaitables) because it explodes the types of operation states.
| template <class _Arg> | ||
| constexpr auto operator()(_Arg&& __arg) const -> _Value | ||
| { | ||
| return static_cast<_Arg&&>(__arg); | ||
| } |
There was a problem hiding this comment.
i think if you change this to:
| template <class _Arg> | |
| constexpr auto operator()(_Arg&& __arg) const -> _Value | |
| { | |
| return static_cast<_Arg&&>(__arg); | |
| } | |
| template <class... _Args> | |
| constexpr auto operator()(_Args&&... __args) const -> _Value | |
| { | |
| return _Value(static_cast<_Args&&>(__args)...); | |
| } |
you no longer need the specialization for std::tuple.
also, should this be be conditionally noexcept?
|
/ok to test 0e15401 |
I can make separate PRs for both of them but a separate fix wasn't/isn't a natural consequence of this work. The fixes just happened to fall out by accident from converting both of them over to |
Implements Stop the Decay P4288R0.
Also contains the following fixes:
continues_onnow implements the standard behavior of scheduling when storing the result datums of the predecessor throwsfinallynow runs the successor even if storing the result datums throwsDoes not fully implement P4288R0's design for
storage_for_completion_signaturebecausestd::tupleis not device compatible.